package com.bsg.upm.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsg.upm.cache.DefinitionMetricCache;
import com.bsg.upm.constant.DictConstants;
import com.bsg.upm.constant.DictTypeConstants;
import com.bsg.upm.constant.MonitorCommonMap;
import com.bsg.upm.constant.SysConstants;
import com.bsg.upm.dao.DictDao;
import com.bsg.upm.dao.HostDao;
import com.bsg.upm.dto.MonitorHostDetailDto;
import com.bsg.upm.dto.MonitorHostDto;
import com.bsg.upm.entity.DictEntity;
import com.bsg.upm.entity.HostEntity;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.http.RespJson;
import com.bsg.upm.http.RespJsonFactory;

/**
 * 
 * @author yucs
 *
 */

@Service
public class MonitorHostService extends BaseService {
	@Resource
	private HostDao hostDao;

	@Resource
	private DictDao dictDao;

	@Resource
	private DefinitionMetricCache definitionMetricCache;

	public RespJson historyHandle(Map<String, Object> paramMap) throws APIException {

		String metric = definitionMetricCache.getMetric(MonitorCommonMap.HOST_TYPE, (String) paramMap.get("metric"));

		if (!metric.contains(";")) {
			return getHistoryMetric(paramMap);
		}

		paramMap.put("metric", metric);
		return getBuldHistoryMetric(paramMap);
	}

	public RespJson noHistoryHandle(Map<String, Object> paramMap) throws APIException {
		String metric = definitionMetricCache.getMetric(MonitorCommonMap.HOST_TYPE, (String) paramMap.get("metric"));
		if (!metric.contains(";")) {
			return getNoHistoryMetric(paramMap);
		}

		paramMap.put("metric", metric);
		return getBuldNoHistoryMetric(paramMap);
	}

	private RespJson getBuldHistoryMetric(Map<String, Object> paramMap) throws APIException {
		String metrics = (String) paramMap.get("metric");
		List<String> metricList = Arrays.asList(metrics.split(";"));

		JSONObject jSONObject = new JSONObject();
		for (String metric : metricList) {
			Map<String, Object> newmap = new HashMap<String, Object>(paramMap);
			newmap.put("metric", metric);
			jSONObject.put(metric, getHistoryMetric(newmap).getData());
		}

		return RespJsonFactory.buildOK(jSONObject);
	}

	private RespJson getBuldNoHistoryMetric(Map<String, Object> paramMap) throws APIException {
		String metrics = (String) paramMap.get("metric");
		List<String> metricList = Arrays.asList(metrics.split(";"));

		JSONObject jSONObject = new JSONObject();
		for (String metric : metricList) {
			Map<String, Object> newmap = new HashMap<String, Object>(paramMap);
			newmap.put("metric", metric);
			jSONObject.put(metric, getNoHistoryMetric(newmap).getData());
		}

		return RespJsonFactory.buildOK(jSONObject);
	}

	public RespJson getHistoryMetric(Map<String, Object> paramMap) throws APIException {
		try {
			JSONArray retJsonArray = new JSONArray();
			String siteId = null;
			String relateHost = null;

			String hostId = (String) paramMap.get("hostId");
			String start = (String) paramMap.get("start_time");
			String end = (String) paramMap.get("end_time");
			String metric = definitionMetricCache.getMetric(MonitorCommonMap.HOST_TYPE,
					(String) paramMap.get("metric"));

			
			String compress = "false";
		 	if (paramMap.containsKey("compress")){
				 compress = (String) paramMap.get("compress");
			}
			
			HostEntity hostEntity = hostDao.get(hostId);

			if (hostEntity == null) {
				return RespJsonFactory.buildOK(retJsonArray);
			}

			siteId = hostEntity.getCluster().getArea().getSite().getId();
			relateHost = hostEntity.getRelateId();

			String url = String.format("/%s/hosts/%s?start_time=%s&end_time=%s&metric=%s&compress=%s",
					SysConstants.HS_VERSION, relateHost, start, end, metric,compress);

			RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_HS, url);

			if (httpRespJson.getStatus() != HttpStatus.SC_OK) {
				logger.error("get horus fail:" + httpRespJson);
				throw new APIException(httpRespJson.getMsg());
			}
 
			JSONObject metrics= (JSONObject)httpRespJson.getData();
			return RespJsonFactory.buildOK(getHistoryFromcommonType(metrics));

		} catch (Exception e) {
			logger.error("getHistoryMetric fail:", e);
			throw new APIException("getHistoryMetric fail:" + e.getMessage());
		}

	}

	public RespJson getNoHistoryMetric(Map<String, Object> paramMap) throws APIException {
		try {

			JSONObject jSONObject = new JSONObject();
			String siteId = null;
			String relateHost = null;

			String hostId = (String) paramMap.get("hostId");
			String metric = definitionMetricCache.getMetric(MonitorCommonMap.HOST_TYPE,
					(String) paramMap.get("metric"));

			long end = System.currentTimeMillis() / 1000;
			long start = end - 60 * 5;

			HostEntity hostEntity = hostDao.get(hostId);

			if (hostEntity == null) {
				return RespJsonFactory.buildOK(jSONObject);
			}

			siteId = hostEntity.getCluster().getArea().getSite().getId();
			relateHost = hostEntity.getRelateId();

			String url = String.format("/%s/hosts/%s?start_time=%d&end_time=%d&metric=%s",
					SysConstants.HS_VERSION, relateHost, start, end, metric);

			RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_HS, url);

			if (httpRespJson.getStatus() != HttpStatus.SC_OK) {
				logger.error("get horus fail:" + httpRespJson);
				throw new APIException(httpRespJson.getMsg());
			}

	 
			JSONObject metrics= (JSONObject)httpRespJson.getData();
			return RespJsonFactory.buildOK(getNoHistoryFromcommonType(metrics));

		} catch (Exception e) {
			logger.error("getNoHistoryMetric fail:", e);
			throw new APIException("getNoHistoryMetric fail:" + e.getMessage());
		}

	}
 
	 

	public RespJson getHostDetail(Map<String, Object> paramMap) throws APIException {
		try {
			MonitorHostDetailDto monitorHostDetailDto = new MonitorHostDetailDto();
			String hostId = (String) paramMap.get("hostId");
			HostEntity host = hostDao.get(hostId);
			if (host == null) {
				return RespJsonFactory.buildOK(monitorHostDetailDto);
			}

			String siteId = host.getCluster().getArea().getSite().getId();
			JSONObject hostMgmJsonObj = null;
			if (StringUtils.isNotBlank(host.getRelateId())) {
				hostMgmJsonObj = getHostMgmInfo(siteId, host.getRelateId());
			}

			monitorHostDetailDto = getShowDetailDto(host, hostMgmJsonObj);

			return RespJsonFactory.buildOK(monitorHostDetailDto);

		} catch (Exception e) {
			logger.error("getHostDetail fail:", e);
			throw new APIException("getHostDetail fail:" + e.getMessage());
		}
	}

	public RespJson list(Map<String, Object> paramMap) throws APIException {
		try {
			JSONArray retJsonArray = new JSONArray();
			List<HostEntity> hosts = hostDao.list(paramMap);
			if (hosts.size() == 0) {
				return RespJsonFactory.buildOK(retJsonArray);
			}

			String siteId = hosts.get(0).getCluster().getArea().getSite().getId();

			JSONArray hostMgmRespJsonArr = getHostMgmInfoArr(siteId);

			for (HostEntity host : hosts) {

				JSONObject hostMgmJsonObj = null;

				if (StringUtils.isNotBlank(host.getRelateId())) {
					hostMgmJsonObj = findMgmHostInfo(hostMgmRespJsonArr, host.getRelateId());
				}

				MonitorHostDto monitorHostDto = getShowDto(host, hostMgmJsonObj);
				retJsonArray.add(monitorHostDto);
			}

			return RespJsonFactory.buildOK(retJsonArray);

		} catch (Exception e) {
			logger.error("主机监控查询异常", e);
			throw new APIException("主机监控查询异常:" + e.getMessage());
		}
	}

	public RespJson getThreshold() throws APIException {
		try {
			JSONObject obj = new JSONObject();

			String valueStr = dictTypeCache.getTextFromCache(DictTypeConstants.MONITOR_THRESHOLD,
					DictConstants.MONITOR_HOST_CODE);
			obj.put("value", new Integer(valueStr));

			return RespJsonFactory.buildOK(obj);

		} catch (Exception e) {
			logger.error("获取主机监控阀值异常", e);
			throw new APIException("获取主机监控阀值异常:" + e.getMessage());
		}

	}

	public RespJson updateThreshold(Integer value) throws APIException {
		try {

			DictEntity dict = dictDao.getByDictTypeCodeAndDictCode(DictTypeConstants.MONITOR_THRESHOLD,
					DictConstants.MONITOR_HOST_CODE);

			dict.setName(value.toString());
			dictTypeCache.updateDict(dict);

			return RespJsonFactory.buildOK();

		} catch (Exception e) {
			logger.error("更新主机监控阀值 异常", e);
			throw new APIException("更新主机监控阀值 异常:" + e.getMessage());
		}

	}

	private MonitorHostDetailDto getShowDetailDto(HostEntity host, JSONObject hostMgmJsonObj) {
		MonitorHostDetailDto monitorHostDetailDto = new MonitorHostDetailDto();
		monitorHostDetailDto.setAreaId(host.getCluster().getArea().getId());
		monitorHostDetailDto.setAreaName(host.getCluster().getArea().getName());

		monitorHostDetailDto.setClusterId(host.getCluster().getId());
		monitorHostDetailDto.setClusterName(host.getCluster().getName());

		monitorHostDetailDto.setName(host.getName());
		monitorHostDetailDto.setId(host.getId());
		monitorHostDetailDto.setRelateId(host.getRelateId());

		monitorHostDetailDto.setSshIp(host.getSshIp());

		monitorHostDetailDto.setRoom(host.getRoom());
		monitorHostDetailDto.setSeat(host.getSeat());

		if (hostMgmJsonObj != null) {
			int cpuCount = hostMgmJsonObj.getJSONObject("Engine").getIntValue("cpus");
			monitorHostDetailDto.setCpuCount(cpuCount);

			int cpuFree = hostMgmJsonObj.getJSONObject("Engine").getIntValue("free_cpus");
			monitorHostDetailDto.setCpuUsed(cpuCount - cpuFree);

			long memCount = hostMgmJsonObj.getJSONObject("Engine").getLongValue("memory");
			monitorHostDetailDto.setMemCount(memCount);

			long memFree = hostMgmJsonObj.getJSONObject("Engine").getLongValue("free_memory");
			monitorHostDetailDto.setMemUsed(memCount - memFree);

			monitorHostDetailDto.setEnabled(hostMgmJsonObj.getBoolean("enabled"));
			monitorHostDetailDto.setEnabledText(dictTypeCache.getTextFromCache(DictTypeConstants.STATUS_ENABLED,
					String.valueOf(monitorHostDetailDto.getEnabled())));

			String register_at = hostMgmJsonObj.getString("register_at");
			monitorHostDetailDto.setJoinTime(register_at);

			List<Map<String, Long>> localHddList = new ArrayList<Map<String, Long>>();
			List<Map<String, Long>> localSsdList = new ArrayList<Map<String, Long>>();
			List<Map<String, Long>> otherdiskList = new ArrayList<Map<String, Long>>();

			JSONArray volumeArr = hostMgmJsonObj.getJSONArray("volume_drivers");
			for (int i = 0; i < volumeArr.size(); i++) {
				Map<String, Long> temp = new HashMap<String, Long>();

				JSONObject volume = volumeArr.getJSONObject(i);
				String volumetype = volume.getString("type");

				switch (volumetype) {

				case "local:HDD":

					temp.put("total", volume.getLong("total"));
					temp.put("used", volume.getLong("total") - volume.getLong("free"));
					localHddList.add(temp);
					break;

				case "local:SSD":
					temp.put("total", volume.getLong("total"));
					temp.put("free", volume.getLong("total") - volume.getLong("free"));
					localSsdList.add(temp);
					break;

				default:
					temp.put("total", volume.getLong("total"));
					temp.put("free", volume.getLong("total") - volume.getLong("free"));
					otherdiskList.add(temp);
					break;
				}
			}

			monitorHostDetailDto.setLocalHdds(localHddList);
			monitorHostDetailDto.setLocalSsds(localSsdList);
			monitorHostDetailDto.setOtherdisks(otherdiskList);

		}

		return monitorHostDetailDto;
	}

	private MonitorHostDto getShowDto(HostEntity host, JSONObject hostMgmJsonObj) {
		MonitorHostDto monitorHostDto = new MonitorHostDto();

		monitorHostDto.setAreaId(host.getCluster().getArea().getId());
		monitorHostDto.setAreaName(host.getCluster().getArea().getName());

		monitorHostDto.setClusterId(host.getCluster().getId());
		monitorHostDto.setClusterName(host.getCluster().getName());

		monitorHostDto.setName(host.getName());
		monitorHostDto.setId(host.getId());

		monitorHostDto.setSshIp(host.getSshIp());

		if (hostMgmJsonObj != null) {
			int cpuCount = hostMgmJsonObj.getJSONObject("Engine").getIntValue("cpus");
			monitorHostDto.setCpuCount(cpuCount);

			int cpuFree = hostMgmJsonObj.getJSONObject("Engine").getIntValue("free_cpus");
			monitorHostDto.setCpuUsed(cpuCount - cpuFree);

			long memCount = hostMgmJsonObj.getJSONObject("Engine").getLongValue("memory");
			monitorHostDto.setMemCount(memCount);

			long memFree = hostMgmJsonObj.getJSONObject("Engine").getLongValue("free_memory");
			monitorHostDto.setMemUsed(memCount - memFree);

			List<Map<String, Long>> localHddList = new ArrayList<Map<String, Long>>();
			List<Map<String, Long>> localSsdList = new ArrayList<Map<String, Long>>();
			List<Map<String, Long>> otherdiskList = new ArrayList<Map<String, Long>>();

			JSONArray volumeArr = hostMgmJsonObj.getJSONArray("volume_drivers");
			for (int i = 0; i < volumeArr.size(); i++) {
				Map<String, Long> temp = new HashMap<String, Long>();

				JSONObject volume = volumeArr.getJSONObject(i);
				String volumetype = volume.getString("type");

				switch (volumetype) {

				case "local:HDD":
					temp.put("total", volume.getLong("total"));
					temp.put("used", volume.getLong("total") - volume.getLong("free"));
					localHddList.add(temp);
					break;

				case "local:SSD":
					temp.put("total", volume.getLong("total"));
					temp.put("used", volume.getLong("total") - volume.getLong("free"));
					localSsdList.add(temp);
					break;

				default:
					temp.put("total", volume.getLong("total"));
					temp.put("used", volume.getLong("total") - volume.getLong("free"));
					otherdiskList.add(temp);
					break;
				}
			}

			monitorHostDto.setLocalHdds(localHddList);
			monitorHostDto.setLocalSsds(localSsdList);
			monitorHostDto.setOtherdisks(otherdiskList);

		}

		return monitorHostDto;
	}

	private JSONArray getHostMgmInfoArr(String siteId) throws APIException {

		String url = "/" + SysConstants.MGM_VERSION + "/hosts";
		RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_MGM, url);

		if (httpRespJson.getStatus() != HttpStatus.SC_OK) {
			throw new APIException(httpRespJson.getMsg());
		}

		return (JSONArray) httpRespJson.getData();

	}

	private JSONObject getHostMgmInfo(String siteId, String hostId) throws APIException {

		String url = "/" + SysConstants.MGM_VERSION + "/hosts/" + hostId;
		RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_MGM, url);

		if (httpRespJson.getStatus() != HttpStatus.SC_OK) {
			throw new APIException(httpRespJson.getMsg());
		}

		return (JSONObject) httpRespJson.getData();

	}

	private JSONObject findMgmHostInfo(JSONArray mgmHostRespJsonArr, String id) {
		if (mgmHostRespJsonArr == null) {
			return null;
		}

		for (int i = 0; i < mgmHostRespJsonArr.size(); i++) {
			JSONObject hostJsonObj = mgmHostRespJsonArr.getJSONObject(i);

			if (hostJsonObj.getString("id").equals(id)) {
				return hostJsonObj;
			}
		}

		return null;
	}
}
